package jrain.fw.http.common.rest;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jrain.fw.core.log.Logger;
import jrain.fw.core.log.LoggerFactory;
import jrain.fw.core.rest.RestMethod;
import jrain.fw.core.rest.RestService;
import jrain.fw.core.service.DestroyService;
import jrain.fw.core.service.InitService;
import jrain.fw.core.service.Service;
import jrain.fw.core.service.ServiceConst;
import jrain.fw.core.utils.FwUtils;
import jrain.fw.http.common.consts.HttpCfg;
import jrain.fw.http.common.consts.HttpConsts;
import jrain.utils.cls.ClassUtils;
import jrain.utils.collection.CollectionUtils;
import jrain.utils.exception.ServiceException;
import jrain.utils.lang.StringUtils;
import jrain.utils.url.UrlUtils;

/**
 * <pre>
 * 作者：3244924214@qq.com 
 * 描述：Rest服务提供者
 * </pre>
 */
@Service(group = HttpConsts.S_HTTP_REST_PROVIDER, module = ServiceConst.M_HTTP_COMMON)
public class DefaultRestProvider implements RestProvider, InitService, DestroyService {

	private static final Logger log = LoggerFactory.getLogger("http-rest-provider");
	private static final Map<Pattern, RestBean> restMap = new HashMap<>();
	private static final AtomicBoolean init = new AtomicBoolean(false);

	public boolean handler(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String requestUrl = StringUtils.trimNull(request.getRequestURI());
		Set<Pattern> keySet = restMap.keySet();
		boolean b = false;
		for (Pattern key : keySet) {
			if (key.matcher(requestUrl).find()) {
				RestBean restBean = restMap.get(key);
				restBean.getMethod().invoke(restBean.getObj(), request, response);
				b = true;
				break;
			}
		}
		return b;
	}

	public void init() {
		if (!init.getAndSet(true)) {
			try {
				String pkgs = StringUtils.trimNull(FwUtils.getFwCfg().get(HttpCfg.httpRestScanPkgs.getName()), HttpCfg.httpRestScanPkgs.getValue());
				List<String> pkgList = CollectionUtils.valueOfList(pkgs);
				log.info("http rest provider scan pkgs {}", pkgs);
				for (String string : pkgList) {
					Set<Class<?>> list = ClassUtils.getClasses(string);
					for (Class<?> claz : list) {
						RestService service = claz.getAnnotation(RestService.class);
						if (service != null) {
							String key = service.name();
							Method[] methods = claz.getDeclaredMethods();
							for (Method method : methods) {
								RestMethod restUrl = method.getAnnotation(RestMethod.class);
								if (restUrl != null) {
									String url = restUrl.name();
									if (!StringUtils.isEmpty(url)) {
										String rsUrl = UrlUtils.joinUrl(key, url);
										restMap.put(Pattern.compile(rsUrl), new RestBean(claz.newInstance(), method));
										log.info("http rest provider  name:{} class:{}", rsUrl, claz.getName());
									}
								}
							}

						}
					}
				}
			} catch (Exception e) {
				String msg = "http provider error";
				log.error(msg, e);
				throw new ServiceException(msg, e);
			}
		}
	}

	public void destroy() {
		if (init.get()) {
			restMap.clear();
			init.set(false);
		}
	}

}
